home *** CD-ROM | disk | FTP | other *** search
- #! /usr/local/bin/python
- #
- # $Id: bdf2pil.py,v 1.1.1.1 1998/08/18 13:08:00 sjoerd Exp $
- #
- # File:
- # bdf2pil.py -- font compiler for X bitmap distribution files
- #
- # Description:
- # This utility converts a BDF font to an image file with an
- # associated font metrics file.
- #
- # History:
- # 96-05-16 fl: Created (after an idea from David Ascher)
- # 96-08-07 fl: Font metrics file uses network byte order
- #
- # Copyright (c) Fredrik Lundh 1996. All rights reserved.
- #
-
- VERSION = "1.0"
-
-
- # HACK
- try:
- import Image
- except:
- import sys
- sys.path.insert(0, ".")
- import Image
-
-
- # --------------------------------------------------------------------
- # Parse X Bitmap Distribution Format (BDF)
- # --------------------------------------------------------------------
-
- import string
-
- bdf_slant = {
- "R": "Roman",
- "I": "Italic",
- "O": "Oblique",
- "RI": "Reverse Italic",
- "RO": "Reverse Oblique",
- "OT": "Other"
- }
-
- bdf_spacing = {
- "P": "Proportional",
- "M": "Monospaced",
- "C": "Cell"
- }
-
- def bdf_char(f):
-
- # skip to STARTCHAR
- while 1:
- s = f.readline()
- if not s:
- return None
- if s[:9] == "STARTCHAR":
- break
- id = string.strip(s[9:])
-
- # load symbol properties
- props = {}
- while 1:
- s = f.readline()
- if not s or s[:6] == "BITMAP":
- break
- i = string.find(s, " ")
- props[s[:i]] = s[i+1:-1]
-
- # load bitmap
- bitmap = []
- while 1:
- s = f.readline()
- if not s or s[:7] == "ENDCHAR":
- break
- bitmap.append(s[:-1])
- bitmap = string.join(bitmap, "")
-
- [w, h, x, y] = map(string.atoi, string.split(props["BBX"]))
- [dx, dy] = map(string.atoi, string.split(props["DWIDTH"]))
-
- bbox = (dx, dy, x, y, x+w, y+h)
-
- return id, string.atoi(props["ENCODING"]), bbox, bitmap
-
-
- def bdf2font(filename):
-
- f = open(filename)
-
- s = f.readline()
- if s[:13] != "STARTFONT 2.1":
- print filename, "is not a valid BDF file (ignoring)"
- return None
-
- print filename
-
- props = {}
- comments = []
-
- while 1:
- s = f.readline()
- if not s or s[:13] == "ENDPROPERTIES":
- break
- i = string.find(s, " ")
- props[s[:i]] = s[i+1:-1]
- if s[:i] in ["COMMENT", "COPYRIGHT"]:
- if string.find(s, "LogicalFontDescription") < 0:
- comments.append(s[i+1:-1])
-
- font = string.split(props["FONT"], "-")
-
- font[4] = bdf_slant[font[4]]
- font[11] = bdf_spacing[font[11]]
-
- ascent = string.atoi(props["FONT_ASCENT"])
- descent = string.atoi(props["FONT_DESCENT"])
-
- fontname = string.join(font[1:], ";")
-
- print "#", fontname
- #for i in comments:
- # print "#", i
-
- font = []
- while 1:
- c = bdf_char(f)
- if not c:
- break
- id, code, bbox, bits = c
- if code >= 0:
- font.append((code, bbox, bits))
-
- return font, fontname, ascent, descent
-
-
- # --------------------------------------------------------------------
- # Translate font to image
- # --------------------------------------------------------------------
-
- def font2image(font, ascent, descent):
-
- metrics = [None] * 256
-
- # create glyph images for all characters in this font
- width = height = 0
- glyph = [None]*256
- for id, (dx, dy, b0, b1, b2, b3), bits in font:
- w, h = b2-b0, b3-b1
- if w > 0 and h > 0:
- i = Image.core.new("L", (w, h))
- height = max(height, h)
- d = Image.core.hex_decoder("1")
- d.setimage(i)
- d.decode(bits)
- glyph[id] = i
- width = width + w
-
- # pack the glyphs into a large image
- x = 0
- bboxes = {}
- i = Image.core.fill("L", (width, height), 0)
- for id, (dx, dy, b0, b1, b2, b3), bits in font:
- w, h = b2-b0, b3-b1
- if w > 0 and h > 0:
- bbox = (x, 0, x+w, h)
- metrics[id] = (dx, dy), (b0, b1, b2, b3), bbox
- i.paste(glyph[id], bbox)
- x = x + w
- bboxes[id] = bbox
-
- return i, bboxes
-
- def puti16(fp, values):
- # write network order (big-endian) 16-bit sequence
- for v in values:
- fp.write(chr(v>>8&255) + chr(v&255))
-
- # --------------------------------------------------------------------
- # MAIN
- # --------------------------------------------------------------------
-
- import glob, os, sys
-
- print "BDF2PIL", VERSION, "-- Font compiler for X BDF fonts."
- print "Copyright (c) Fredrik Lundh 1996. All rights reserved."
-
- if len(sys.argv) <= 1:
- print
- print "Usage: bdf2pil files..."
- print
- print "BDF files are converted to a bitmap file (currently"
- print "using PBM format) and a font metrics file (PIL)."
- sys.exit(1)
-
- files = []
- for f in sys.argv[1:]:
- files = files + glob.glob(f)
-
- for file in files:
- font, fontname, ascent, descent = bdf2font(file)
- if font:
- image, srcbbox = font2image(font, ascent, descent)
- # to be changed to PCX or something...
- image.save_ppm(os.path.splitext(file)[0] + ".pbm")
- # create font metrics file
- metrics = {}
- for id, xy_bbox, bits in font:
- x, y, x0, y0, x1, y1 = xy_bbox
- metrics[id] = (x, y, x0, ascent-y1, x1, ascent-y0) + srcbbox[id]
- fp = open(os.path.splitext(file)[0] + ".pil", "wb")
- fp.write("PILfont\n")
- fp.write("%s\n" % fontname)
- fp.write("DATA\n")
- for id in range(256):
- try:
- puti16(fp, metrics[id])
- except KeyError:
- puti16(fp, (0,) * 10)
- fp.close()
-
- # --------------------------------------------------------------------
- # Font metrics format:
- # "PILfont" LF
- # fontdescriptor LF
- # (optional) key=value... LF
- # "DATA" LF
- # binary data: 256*10*2 bytes (dx, dy, dstbox, srcbox)
- #
- # To place a character, cut out srcbox and paste at dstbox,
- # relative to the character position. Then move the character
- # position according to dx, dy.
- # --------------------------------------------------------------------
-
-